package org.example.springoauth2.securitycommon.factory;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.example.springoauth2.securitycommon.entity.JdbcUser;
import org.example.springoauth2.securitycommon.entity.JdbcUserAuth;
import org.example.springoauth2.securitycommon.util.TenantHolder;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;
import java.util.List;

/**
 * @author hzq
 * @date 2021/9/11 15:38
 */
@Slf4j
public class SysUserFactory implements ApplicationRunner {

    private static PasswordEncoder PASSWORD_ENCODER = PasswordEncoderFactories.createDelegatingPasswordEncoder();
    private static List<JdbcUser> JDBC_USERS = new ArrayList<>();
    private static List<JdbcUserAuth> JDBC_USER_AUTH = new ArrayList<>();
    private static String[] GENDER_ARR = {"男", "女", "未知"};
    private static String[] USER_TYPE = {"员工", "客户"};
    public static final String[] AUTH_TYPE = {"password", "phone", "wx_openid", "tt_openid"};

    @Override
    public void run(ApplicationArguments args) throws Exception {
        long start = System.currentTimeMillis();
        log.info("开始生成用户信息----生成50个用户----");
        String BJX = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮卞齐康伍余元卜顾孟平黄和穆萧尹姚邵湛汪祁毛禹狄米贝明臧计伏成戴谈宋茅庞熊纪舒屈项祝董梁杜阮蓝闵席季麻强贾路娄危江童颜郭梅盛林刁钟徐邱骆高夏蔡田樊胡凌霍虞万支柯昝管卢莫经房裘缪干解应宗丁宣贲邓郁单杭洪包诸左石崔吉钮龚程嵇邢滑裴陆荣翁荀羊於惠甄曲家封芮羿储靳汲邴糜松井段富巫乌焦巴弓牧隗山谷车侯宓蓬全郗班仰秋仲伊宫";
        for (int i = 0; i < 50; i++) {
            JdbcUser jdbcUser = JdbcUser.builder()
                    .id(i)
                    .unionId(UUID.fastUUID().toString())
                    .tenantId(i % 4)
                    .userType(USER_TYPE[i % 2])
                    .nickname(RandomUtil.randomString(BJX, 3))
                    .gender(GENDER_ARR[i % 3])
                    .build();
            JDBC_USERS.add(jdbcUser);
            // 员工 使用三种方式登录 password phone wx_openid
            // 客户 使用两种方式登录 wx_openid tt_openid
            generateBaseJdbcUserAuth2(jdbcUser);
            generateAppJdbcUserAuth(jdbcUser);
        }
        log.info("生成用户信息完成----耗时:{}----", (System.currentTimeMillis() - start));
    }

    public static JdbcUser queryJdbcUser(String authType, String key) {
        JdbcUserAuth jdbcUserAuth = queryJdbcUserAuth(authType, key);
        if (jdbcUserAuth == null)
            return null;
        for (JdbcUser jdbcUser : JDBC_USERS) {
            if (jdbcUser.getUnionId().equals(jdbcUserAuth.getUnionId())) {
                JdbcUser build = JdbcUser.builder().jdbcUserAuth(jdbcUserAuth).build();
                BeanUtils.copyProperties(jdbcUser, build, "jdbcUserAuth");
                return build;
            }
        }
        return null;
    }

    public static JdbcUser queryJdbcUser(String unionId) {
        for (JdbcUser jdbcUser : JDBC_USERS) {
            if (jdbcUser.getUnionId().equals(unionId)) {
                JdbcUser build = JdbcUser.builder().build();
                BeanUtils.copyProperties(jdbcUser, build);
                JdbcUserAuth jdbcUserAuth = JdbcUserAuth.builder()
                        .unionId(jdbcUser.getUnionId())
                        .tenantId(jdbcUser.getTenantId())
                        .secret("N/A").build();
                build.setJdbcUserAuth(jdbcUserAuth);
                return build;
            }
        }
        return null;
    }

    private static JdbcUserAuth queryJdbcUserAuth(String authType, String key) {
        for (JdbcUserAuth jdbcUserAuth : JDBC_USER_AUTH) {
            if (jdbcUserAuth.getAuthType().equals(authType) &&
                    jdbcUserAuth.getKey().equals(key) &&
                    jdbcUserAuth.getTenantId().equals(TenantHolder.get())) {
                if (jdbcUserAuth.getSecret() == null) {
                    jdbcUserAuth.setSecret("N/A");
                }
                return jdbcUserAuth;
            }
        }
        return null;
    }

    private static void generateBaseJdbcUserAuth2(JdbcUser jdbcUser) {
        if (!jdbcUser.getUserType().equals(USER_TYPE[0]))
            return;
        JdbcUserAuth password = JdbcUserAuth.builder()
                .authType(AUTH_TYPE[0])
                .key("username_" + jdbcUser.getId())
                .secret(PASSWORD_ENCODER.encode("password_" + jdbcUser.getId()))
                .tenantId(jdbcUser.getTenantId())
                .unionId(jdbcUser.getUnionId())
                .build();
        JDBC_USER_AUTH.add(password);
        JdbcUserAuth phone = JdbcUserAuth.builder()
                .authType(AUTH_TYPE[1])
                .key("phone_" + jdbcUser.getId())
                .tenantId(jdbcUser.getTenantId())
                .unionId(jdbcUser.getUnionId())
                .build();
        JDBC_USER_AUTH.add(phone);
    }

    private static void generateAppJdbcUserAuth(JdbcUser jdbcUser) {
        JdbcUserAuth wxOpenid = JdbcUserAuth.builder()
                .authType(AUTH_TYPE[2])
                .key("wx_openid_" + jdbcUser.getId())
                .tenantId(jdbcUser.getTenantId())
                .unionId(jdbcUser.getUnionId())
                .build();
        JDBC_USER_AUTH.add(wxOpenid);
        if (!jdbcUser.getUserType().equals(USER_TYPE[1]))
            return;
        JdbcUserAuth ttOpenid = JdbcUserAuth.builder()
                .authType(AUTH_TYPE[3])
                .key("tt_openid_" + jdbcUser.getId())
                .tenantId(jdbcUser.getTenantId())
                .unionId(jdbcUser.getUnionId())
                .build();
        JDBC_USER_AUTH.add(ttOpenid);
    }
}
